/****************************************************
	文件：WorldState.cs
	作者：HuskyT
	邮箱：1005240602@qq.com
	日期：2020/8/26 17:47:18
	功能：世界状态
*****************************************************/

using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;

namespace AIFramework.HTN
{
    public enum E_WSProperties
    {
        /// <summary>
        /// 所在位置（Enum）
        /// </summary>
        WS_Location,
        /// <summary>
        /// 是否可以看见敌人（Bool）
        /// </summary>
        WS_CanSeeEnemy,
        /// <summary>
        /// 树干（武器）耐久度（Int）
        /// </summary>
        WS_TrunkHealth,
        /// <summary>
        /// 最近是否看见过敌人（Bool）
        /// </summary>
        WS_HasSeenEnemyRecently,
        /// <summary>
        /// 近期是否攻击过（Bool）
        /// </summary>
        WS_AttackedRecently,
        /// <summary>
        /// 是否可寻路到敌人位置（Bool）
        /// </summary>
        WS_CanNavigateToEnemy,
    }

    public enum E_Location
    {
        /// <summary>
        /// 在敌人附近
        /// </summary>
        EnemyLocRef,
        /// <summary>
        /// 桥附近
        /// </summary>
        NextBridgeLocRef,
        /// <summary>
        /// 树干附近
        /// </summary>
        FoundTrunk,
        /// <summary>
        /// 最近一次敌人的位置
        /// </summary>
        LastEnemyPos,
    }

    public class WorldState
    {
        /// <summary>
        /// 世界状态数据缓存
        /// </summary>
        private Dictionary<E_WSProperties, Enum> mEnum_WS;
        private Dictionary<E_WSProperties, int> mInt_WS;
        private Dictionary<E_WSProperties, bool> mBool_WS;
        private Dictionary<E_WSProperties, float> mFloat_WS;
        private Dictionary<E_WSProperties, object> mObject_WS;

        private EntityBase mSelf;
        /// <summary>
        /// 该世界状态所属实体
        /// </summary>
        public EntityBase Self { get => mSelf; }

        public WorldState(EntityBase entity)
        {
            mSelf = entity;
            Reset();
        }

        /// <summary>
        /// 重置数据
        /// </summary>
        public void Reset()
        {
            mEnum_WS = new Dictionary<E_WSProperties, Enum>();
            mInt_WS = new Dictionary<E_WSProperties, int>();
            mBool_WS = new Dictionary<E_WSProperties, bool>();
            mFloat_WS = new Dictionary<E_WSProperties, float>();
            mObject_WS = new Dictionary<E_WSProperties, object>();

            Add(E_WSProperties.WS_CanSeeEnemy, false);
            Add(E_WSProperties.WS_Location, E_Location.NextBridgeLocRef);
            Add(E_WSProperties.WS_TrunkHealth, 0);
            Add(E_WSProperties.WS_AttackedRecently, false);
            Add(E_WSProperties.WS_CanNavigateToEnemy, true);
        }

        #region Add：添加世界状态属性
        /// <summary>
        /// 添加世界状态属性
        /// </summary>
        /// <param name="property">属性枚举</param>
        /// <param name="value">状态值</param>
        public void Add(E_WSProperties property, Enum value)
        {
            mEnum_WS.Add(property, value);
        }
        /// <summary>
        /// 添加世界状态属性
        /// </summary>
        /// <param name="property">属性枚举</param>
        /// <param name="value">状态值</param>
        public void Add(E_WSProperties property, int value)
        {
            mInt_WS.Add(property, value);
        }
        /// <summary>
        /// 添加世界状态属性
        /// </summary>
        /// <param name="property">属性枚举</param>
        /// <param name="value">状态值</param>
        public void Add(E_WSProperties property, bool value)
        {
            mBool_WS.Add(property, value);
        }
        /// <summary>
        /// 添加世界状态属性
        /// </summary>
        /// <param name="property">属性枚举</param>
        /// <param name="value">状态值</param>
        public void Add(E_WSProperties property, float value)
        {
            mFloat_WS.Add(property, value);
        }
        /// <summary>
        /// 添加世界状态属性
        /// </summary>
        /// <param name="property">属性枚举</param>
        /// <param name="value">状态值</param>
        public void Add(E_WSProperties property, object value)
        {
            mObject_WS.Add(property, value);
        }
        #endregion

        #region Getxxx：获取指定属性
        /// <summary>
        /// 获取指定属性
        /// </summary>
        /// <param name="propType">属性枚举</param>
        /// <returns></returns>
        public Enum GetEnum(E_WSProperties propType)
        {
            return mEnum_WS[propType];
        }
        /// <summary>
        /// 获取指定属性
        /// </summary>
        /// <param name="propType">属性枚举</param>
        /// <returns></returns>
        public int GetInt(E_WSProperties propType)
        {
            return mInt_WS[propType];
        }
        /// <summary>
        /// 获取指定属性
        /// </summary>
        /// <param name="propType">属性枚举</param>
        /// <returns></returns>
        public bool GetBool(E_WSProperties propType)
        {
            return mBool_WS[propType];
        }
        /// <summary>
        /// 获取指定属性
        /// </summary>
        /// <param name="propType">属性枚举</param>
        /// <returns></returns>
        public float GetFloat(E_WSProperties propType)
        {
            return mFloat_WS[propType];
        }
        /// <summary>
        /// 获取指定属性
        /// </summary>
        /// <param name="propType">属性枚举</param>
        /// <returns></returns>
        public object GetObject(E_WSProperties propType)
        {
            return mObject_WS[propType];
        }
        #endregion

        #region Set：设置世界状态属性
        /// <summary>
        /// 设置世界状态属性
        /// </summary>
        /// <param name="propType">属性枚举</param>
        /// <param name="value">属性值</param>
        /// <returns></returns>
        public bool Set(E_WSProperties propType, Enum value)
        {
            if (mEnum_WS.ContainsKey(propType))
            {
                mEnum_WS[propType] = value;
                return true;
            }
            return false;
        }
        /// <summary>
        /// 设置世界状态属性
        /// </summary>
        /// <param name="propType">属性枚举</param>
        /// <param name="value">属性值</param>
        /// <returns></returns>
        public bool Set(E_WSProperties propType, int value)
        {
            if (mInt_WS.ContainsKey(propType))
            {
                mInt_WS[propType] = value;
                return true;
            }
            return false;
        }
        /// <summary>
        /// 设置世界状态属性
        /// </summary>
        /// <param name="propType">属性枚举</param>
        /// <param name="value">属性值</param>
        /// <returns></returns>
        public bool Set(E_WSProperties propType, bool value)
        {
            if (mBool_WS.ContainsKey(propType))
            {
                mBool_WS[propType] = value;
                return true;
            }
            return false;
        }
        /// <summary>
        /// 设置世界状态属性
        /// </summary>
        /// <param name="propType">属性枚举</param>
        /// <param name="value">属性值</param>
        /// <returns></returns>
        public bool Set(E_WSProperties propType, float value)
        {
            if (mFloat_WS.ContainsKey(propType))
            {
                mFloat_WS[propType] = value;
                return true;
            }
            return false;
        }
        /// <summary>
        /// 设置世界状态属性
        /// </summary>
        /// <param name="propType">属性枚举</param>
        /// <param name="value">属性值</param>
        /// <returns></returns>
        public bool Set(E_WSProperties propType, object value)
        {
            if (mObject_WS.ContainsKey(propType))
            {
                mObject_WS[propType] = value;
                return true;
            }
            return false;
        }
        #endregion

        #region SetNew：设置世界状态属性（可以设置/新增）
        /// <summary>
        /// 设置世界状态属性（可以设置/新增）
        /// </summary>
        /// <param name="propType"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public void SetNew(E_WSProperties propType, Enum value)
        {
            if (mEnum_WS.ContainsKey(propType))
            {
                mEnum_WS[propType] = value;
            }
            else
            {
                mEnum_WS.Add(propType, value);
            }
        }
        /// <summary>
        /// 设置世界状态属性（可以设置/新增）
        /// </summary>
        /// <param name="propType"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public void SetNew(E_WSProperties propType, int value)
        {
            if (mInt_WS.ContainsKey(propType))
            {
                mInt_WS[propType] = value;
            }
            else
            {
                mInt_WS.Add(propType, value);
            }
        }
        /// <summary>
        /// 设置世界状态属性（可以设置/新增）
        /// </summary>
        /// <param name="propType"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public void SetNew(E_WSProperties propType, bool value)
        {
            if (mBool_WS.ContainsKey(propType))
            {
                mBool_WS[propType] = value;
            }
            else
            {
                mBool_WS.Add(propType, value);
            }
        }
        /// <summary>
        /// 设置世界状态属性（可以设置/新增）
        /// </summary>
        /// <param name="propType"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public void SetNew(E_WSProperties propType, float value)
        {
            if (mFloat_WS.ContainsKey(propType))
            {
                mFloat_WS[propType] = value;
            }
            else
            {
                mFloat_WS.Add(propType, value);
            }
        }
        /// <summary>
        /// 设置世界状态属性（可以设置/新增）
        /// </summary>
        /// <param name="propType"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public void SetNew(E_WSProperties propType, object value)
        {
            if (mObject_WS.ContainsKey(propType))
            {
                mObject_WS[propType] = value;
            }
            else
            {
                mObject_WS.Add(propType, value);
            }
        }
        #endregion

        #region Contains：是否包含某些条件
        /// <summary>
        /// 是否包含某些条件
        /// </summary>
        /// <param name="cond"></param>
        /// <returns></returns>
        public bool Contains(KeyValuePair<E_WSProperties, Enum> cond)
        {
            if (mEnum_WS.ContainsKey(cond.Key) == false || mEnum_WS[cond.Key] != cond.Value)
            {
                return false;
            }
            return true;
        }
        /// <summary>
        /// 是否包含某些条件
        /// </summary>
        /// <param name="cond"></param>
        /// <returns></returns>
        public bool Contains(KeyValuePair<E_WSProperties, int> cond)
        {
            if (mInt_WS.ContainsKey(cond.Key) == false || mInt_WS[cond.Key] != cond.Value)
            {
                return false;
            }
            return true;
        }
        /// <summary>
        /// 是否包含某些条件
        /// </summary>
        /// <param name="cond"></param>
        /// <returns></returns>
        public bool Contains(KeyValuePair<E_WSProperties, bool> cond)
        {
            if (mBool_WS.ContainsKey(cond.Key) == false || mBool_WS[cond.Key] != cond.Value)
            {
                return false;
            }
            return true;
        }
        /// <summary>
        /// 是否包含某些条件
        /// </summary>
        /// <param name="cond"></param>
        /// <returns></returns>
        public bool Contains(KeyValuePair<E_WSProperties, float> cond)
        {
            if (mFloat_WS.ContainsKey(cond.Key) == false || mFloat_WS[cond.Key] != cond.Value)
            {
                return false;
            }
            return true;
        }
        /// <summary>
        /// 是否包含某些条件
        /// </summary>
        /// <param name="cond"></param>
        /// <returns></returns>
        public bool Contains(KeyValuePair<E_WSProperties, object> cond)
        {
            if (mObject_WS.ContainsKey(cond.Key) == false || mObject_WS[cond.Key] != cond.Value)
            {
                return false;
            }
            return true;
        }
        #endregion

        #region CopyFrom：从指定WorldState中复制数据
        /// <summary>
        /// 从指定WorldState中复制数据
        /// </summary>
        /// <param name="ws">世界状态</param>
        public void CopyFrom(WorldState ws)
        {
            foreach (var item in ws.mEnum_WS)
            {
                SetNew(item.Key, item.Value);
            }
            foreach (var item in ws.mInt_WS)
            {
                SetNew(item.Key, item.Value);
            }
            foreach (var item in ws.mBool_WS)
            {
                SetNew(item.Key, item.Value);
            }
            foreach (var item in ws.mFloat_WS)
            {
                SetNew(item.Key, item.Value);
            }
            foreach (var item in ws.mObject_WS)
            {
                SetNew(item.Key, item.Value);
            }
            mSelf = ws.Self;
        }
        #endregion

        /// <summary>
        /// 打印世界状态（测试使用）
        /// </summary>
        public void LogWorldState(string title)
        {
            StringBuilder sb = new StringBuilder();
            foreach (var item in mEnum_WS)
            {
                sb.Append("//世界属性：").Append(item.Key.ToString()).Append("--属性值：").Append(item.Value.ToString()).Append("//\n");
            }
            foreach (var item in mInt_WS)
            {
                sb.Append("//世界属性：").Append(item.Key.ToString()).Append("--属性值：").Append(item.Value.ToString()).Append("//\n");
            }
            foreach (var item in mBool_WS)
            {
                sb.Append("//世界属性：").Append(item.Key.ToString()).Append("--属性值：").Append(item.Value.ToString()).Append("//\n");
            }
            foreach (var item in mFloat_WS)
            {
                sb.Append("//世界属性：").Append(item.Key.ToString()).Append("--属性值：").Append(item.Value.ToString()).Append("//\n");
            }
            foreach (var item in mObject_WS)
            {
                sb.Append("//世界属性：").Append(item.Key.ToString()).Append("--属性值：").Append(item.Value.ToString()).Append("//\n");
            }
            Debug.LogWarning(title + "  LogWorldState：\n" + sb.ToString());
        }
    }
}
